home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / faq / preak.zip / MTEXT.ZIP / LICENSE.ASC next >
PGP Signed Message  |  1993-06-09  |  59KB  |  2,057 lines

  1. -----BEGIN PGP SIGNED MESSAGE-----
  2.  
  3. Guerilla Guide to Licensing Software
  4.  
  5. DRAFT VERSION 0.1
  6.  
  7. Abstract
  8.  
  9. This short article discusses the weaknesses of various licensing schemes
  10. to control the use and distribution of Unix software. In particular,
  11. examples will be given of actual commercial products which can be
  12. "cracked" with a minimum of effort. The intention is to provide
  13. some observations which will be of use to implementers and designers
  14. of software or those integrating licence managers into their products.
  15.  
  16.  
  17.  
  18. DISCLAIMER: I am not recommending that you steal software. The purpose
  19. of this article is to point out to vendors to weaknesses of the schemes
  20. they use. Please do not use this information for illegal purposes.
  21.  
  22. For obvious reasons the author of this document wishes to remain anonymous.
  23.  
  24. Network licence servers or node locked licences have become very
  25. popular in the Unix world over the last few years. Most vendors
  26. now use them, as they provide an easy means to control the use
  27. and distribution of commerical software with a minimum of customer
  28. inconvenience. Unfortunately many of these provide a false sense
  29. of security for the vendor in that any skilled "cracker" can break
  30. the scheme thus turning a demonstration version into an unauthorised 
  31. unlimited licence version or adding licences to an already purchased
  32. version.
  33.  
  34. In particular, many vendors provide demonstration versions of software
  35. which either have expiry dates (fully functional short term licences)
  36. or have limited functionality. This approach is inherently weak in
  37. that it is usually possible to convert this demonstration version
  38. into a fully functional long term version. Vendors like this sort
  39. of scheme because a customer can call up and purchase the product,
  40. and have a licensed version immediately, if he/she has a demonstration
  41. version, say from a CD-ROM library of demonstration programs. However,
  42. in this case, the demonstration version will undoubtedly be distributed
  43. to a lot of potential customers. From the vendor's point of view,
  44. the sort of "cracking" which turns a demonstration version into a "real"
  45. version is probably a more serious problem that "cracking" to gain
  46. extra licences.
  47.  
  48. I'm going to start with a brief overview of the methods most of these
  49. products use to generate licences. Most of the schemes use some
  50. sort of cryptographically strong hash function to give a level
  51. of security. Examples of these are MD2, MD4, MD5, Snefru and the
  52. NIST Secure Hash Standard (FIPS-180). These hash functions all
  53. have the property that it is computationally difficult to determine
  54. the input given the output or to determine two outputs which hash to 
  55. the same value.  The security of the system usually relies on the secrecy 
  56. of the hash function used and the difficulty of inverting that function.
  57.  
  58. a) Node-locked licences. These are licenses to run a certain number
  59. of copies of a product on a single computer. Usually some sort
  60. of unique host identifier is hashed together with the number of
  61. licences, expiry date, and possibly some customer identification information
  62. (company name &c.). The host identifier and number of licences
  63. are stored in plaintext together with the hash value.
  64.  
  65. e.g.
  66. hostid 66777777
  67. hostname foo
  68. licences 7
  69. key 4f4c998319b26020a20ed60e146c7d60
  70.  
  71. For our example the hash function is a function H of
  72. hostid, hostname and licenses, probably constructed using the
  73. composition of some simple string manipulation and either
  74. one of the "secure" hash functions mentioned above or perhaps
  75. a hash function designed by the licensing software vendor.
  76.  
  77. The vendor, given the hostid, hostname and licences, computes
  78. H(hostid,hostname,licences) and gives this to the customer upon
  79. purchase.  The product would check the hash value by computing
  80. H(hostid,hostname,licenses) and checking that value against the licence
  81. key. If they don't match, a violation is detected and presumably the
  82. product will not function correctly. In our specific example if
  83. an unscrupulous customer changes the value to "licences" to 8,
  84. the key the product computes will not match the key value
  85. given by the vendor and a violation will be detected.
  86.  
  87. Now, you might ask, "why is this system inherently weak?". Well, the
  88. answer is sort of obvious, if our unscrupulous user could monitor
  89. the execution of the program in order to find out what the key should be
  90. given altered licensing data, then he/she could "crack" the system.
  91. If a demonstration version has an expiry date, this sort of scheme
  92. might allow someone to change this date and therefore have access
  93. to a "real" version of the product.
  94.  
  95. b) Floating licences:
  96. Are essentially very similar. A licence server runs on a host or
  97. set of hosts. The verification of the key is usually done by the
  98. server on startup. Some sort of protocol (which might include
  99. encryption) is used for client-server communications.
  100.  
  101. The attacks I give below will involve actual modification
  102. of the product in question. None of them took over four hours (and
  103. I'm not a particularly talented hacker).
  104.  
  105. As an aside, an obvious solution to the above would be the use of public
  106. key methods. There are two obvious problems here, the first being that
  107. all such methods are patented and thus the user would have to pay a license
  108. fee. The second is that digital signature algorithms often would produce
  109. keys that are much too large for the average user to type in. Clearly
  110. a 128 byte key (256 hex digits) would be acceptable to most customers, but
  111. if you use something like RSA to sign your licensing information, you
  112. are looking at something on that scale.
  113.  
  114. Types of attacks:
  115. 1. Bypass the licensing routines altogether.
  116. 2. Run the licensing routine but change its return value.
  117. 3. Determine what the licence key "should be" given the other (altered)
  118.    licensing data.
  119. 4. Change the values of certain interesting variables.
  120.  
  121. The attacks I'll discuss will involve the use of some sort of debugger.
  122. The appropriate debugger often depends on the system you are working with.
  123. Usually lower level debuggers are better as little or no symbolic
  124. information will be available (most vendors strip binaries). However,
  125. in many cases if the product is dynamically linked, you can "unstrip" 
  126. the relevant programs to restore much of the symbolic data. Obviously 
  127. you are ahead if there is a routine called check_licence() and you know 
  128. when and where it is called, you have some useful information to attack
  129. the product. (an unstrip program for sun os 4.1 is included with this
  130. file. The same sort of thing works under AIX 3.2 and Solaris 2.x, for 
  131. example).
  132.  
  133. So for licence software designers and integrators.
  134.  
  135. I. First principle. Obscure symbolic information.
  136.    - Strip your binaries. 
  137.    - Statically link if possible. 
  138.    - If you can't statically link, try and obscure the symbol names. One
  139.      way to do this is to obfuscate all of the symbol names in your
  140.      distribution version. (opqcp available in comp.sources.misc vol 13 is
  141.      a useful tool for this, some might argue that using C++ is enough ;-) ).
  142.  
  143.  
  144. The sample attacks will explain some obvious avenues of attack. The
  145. product names will be changed to protect the vendors in question.
  146.  
  147. Example 1. Product A, Sun 4, SUN OS 4.1.1
  148. Product A is a nifty tool. The vendor will send you a demo version
  149. if you call and ask. The demo version is fully functional, but will
  150. expire after a couple of weeks.
  151.  
  152. Step 1 is to unstrip (indeed this one is dynamically linked).
  153.  
  154. Step 2. Change the expiry date in the licence file from 31-Dec-1992 
  155. to 31-Dec-1999 (now the key won't match what the vendor would have given 
  156. us if he/she had given us that expiry date).
  157.  
  158. A little work with adb reveals the following:
  159.  
  160. product A forks before it checks the licensing information. The child
  161. does all the work.
  162.  
  163. So, step 3, reverse the sense of the test after the fork.
  164.  
  165. The source code (which we don't have) looks something like:
  166. if (fork()) {
  167.     /* parent - just die */
  168.     exit(0);
  169. }
  170. else {
  171.     /* child - do the work */
  172. }
  173.  
  174. So, we try and reverse the test. The resulting binary won't work properly
  175. of course, but the point is to get some information on how things work.
  176.  
  177. So we:
  178. cp product_a product_a_hacked_version
  179. adb -w ./product_a_hacked_version
  180. 0x2664  - reverse the sense of this test.
  181. i.e.
  182. change
  183. _main+0x30:     be,a    _main + 0x40
  184. to
  185. _main+0x30:     bne,a   _main + 0x40
  186.  
  187. e.g. you might do this by
  188. 0x2664?w 3280
  189.  
  190.  
  191. It turns out (this is too easy), if you set a breakpoint on strncmp
  192. after doing this, you will find that (on the first call to strncmp) one 
  193. of the parameters contains the value of the key from the licence file and
  194. one of them contains the value the key should have. 
  195.  
  196. One can then proceed by changing the key in the licence file. In this
  197. case, I could change the expiry date to some date in 1999.
  198.  
  199.  
  200. 4> adb ./product_a_hacked_version
  201. strncmp:b
  202. :r 0 1 ./product_a_hacked_version
  203. SIGCHLD 20: child status change
  204. stopped at      _isatty+0x98:   bgeu    _isatty + 0xc0
  205. :c 0
  206. breakpoint      _strncmp:       save    %sp, -0x60, %sp
  207. :s
  208. stopped at      _strncmp+4:     call    __DYNAMIC + 0x60
  209. :s
  210. stopped at      _strncmp+8:     sethi   %hi(0xb000), %g0
  211. $C
  212. _strncmp(0x11330,0x157dc,0x14,0xf7fff314,0xf7fff314,0x63) + 8
  213. _lm_checkout(0xe3f8,0x3ff00000,0x0,0x1,0x0,0xe3b0) + a60
  214. _lm_checkout(0xe3f8,0x3ff00000,0x0,0x1,0x0,0xe3b0) + dc
  215. _main(0x4,0x0,0x0,0x1,0x0,0x834) + 29c
  216. 0x11330?s
  217. __mb_cur_max+0x1fc:             5AA6DC71361F95E20D1C
  218.  
  219. and yes, this is the required key value.
  220.  
  221. ("too easy" you say, this product sells for over $2000 per licence!).
  222.  
  223. Indeed, the "unhacked" version runs nicely with the key and expiry
  224. date in the new licence file. You might say that the vendor was
  225. singularly stupid, but strangely enough, this sort of thing is
  226. very common.
  227.  
  228.  
  229. II. Second Principle.
  230.     Fully functional date locked demonstration versions are dangerous things.
  231.  
  232. III. Third Principle.
  233.     Lock a smart hacker who knows nothing about the internals of your
  234.     product (new employees can be good for this) in a room with your product 
  235.     for a day and see if he/she can crack it. Certainly this sort of 
  236.     thing is standard practice in the design of cryptosystems.
  237.  
  238. IV. Fourth Principle.
  239.     Try and obscure the functioning of your licensing code.
  240.  
  241.  
  242.  
  243. Example 2. The case of product B.
  244. I'm going into somewhat less detail here because this is in a way similar
  245. to product A. Product B is statically linked :-(
  246. Product B is another nifty tool selling for >$1000 per license.
  247.  
  248. The vendor will give you a date locked fully functional version. 
  249. If the licence key is not verified (expired or whatever), product
  250. B comes up in demonstration mode which has restricted functionality.
  251.  
  252. The mode (demonstration or licenced) is controlled by a single boolean 
  253. variable (integer value 0 or 1). This variable is checked when
  254. someone tries one of the restricted functions, and the user
  255. is either permitted to perform the function or not based on the
  256. value of this variable.
  257.  
  258. The way to crack this, of course, was to insert an instruction near
  259. the end of the licensing code which set the data location to the value 1.
  260.  
  261. Clues:
  262. 1. Whenever a restricted function was performed that address was accessed.
  263.    It wasn't accessed otherwise after the initial startup.
  264. 2. Value of 0 or 1 was a dead giveaway. A pointer to a string might have
  265.    been a better choice for the value of TRUE.
  266.  
  267.  
  268.  
  269. Example 3. The case of product C.
  270.  
  271. Product C is less expensive than either of the above. It was somewhat
  272. harder to crack. Product C is also statically linked :-( We start
  273. working from the case where there is an expired demonstration licence.
  274.  
  275.  
  276. We use adb again. The following steps do the trick.
  277.  
  278. 1. Locate main.
  279. 2. Find the call directly from main which prints out a message which
  280.    indicates that the licence file is invalid.
  281. 3. proceed down the "tree" of calls to find the lowest level routine
  282.    which prints this message. A little trial and error shows the conditional
  283.    branch which determines if a key is valid in this routine. Note that
  284.    this happens just after getimeofday is called!
  285.  
  286.             or      %o2, 0x57, %o2
  287.             mov     0x5, %o0
  288.             call    0x412c8
  289.             nop
  290.             ba      0x69e18
  291.             clr     %i3
  292.             ld      [%o5 + 0x37c], %o5
  293.             andcc   %o5, 0x2, %g0
  294.             be,a    0x69e24
  295.             orcc    %g0, %i3, %g0
  296.             call    0x13af50  - this calls gettimeofday(2)
  297.             clr     %o0
  298.             ld      [%i5 + 0x10], %o7
  299.             cmp     %o7, %o0
  300. 0x69e08     bl,a    0x69e24     (originally bgeu,a 0x69e24)
  301.             orcc    %g0, %i3, %g0
  302.             mov     0x1, %l2
  303.             clr     %i3
  304.             clr     %i0
  305.  
  306. Now the expired demo license will serve as a perpetual demo licence.
  307. The demo version is fully functional
  308.  
  309. Now the expired demo license will serve as a perpetual demo licence.
  310. The demo version is fully functional
  311.  
  312.    
  313.  
  314.  
  315. Example 4. The case of product D.
  316.  
  317. Product D is statically linked. 
  318.  
  319. We can bypass the licence routine completely by replacing the
  320. call to it with a nop. The folling is an RS6000 exmaple.
  321.  
  322. 0x10018444 (???) 4818e101         bl   0x101a6544 (???)
  323. replace this with 38600000  lil r3,0
  324.  
  325. again we could determine the routine of interest by finding out
  326. which routine printed the violation message when there was no
  327. licence.
  328.  
  329. Another option in this case was to insert a return instruction just
  330. after the call to the licence routine (which incidentally calls
  331. gethostid first thing and later displays a message about not
  332. being able to get a licence).
  333.  
  334. - From this we might observe, two related principles.
  335.  
  336. V. Fifth Principle. Modularity is a bad thing.
  337. If someone can subvert your code by altering one routine or changing
  338. one variable, then the code is vunerable. Software engineering practice
  339. would seem to dictate that you should have one routine or small set of
  340. routines where all of the licensing code resides. However, this sort
  341. of approach is inherently insecure. For instance in the above the
  342. routine which prints the message indicating a licensing violation was
  343. the routine which verified the licensing data. It would have been much
  344. better to seperate the two.
  345.  
  346. VI. Sixth Principle. When you write code for the licensing system, make 
  347. sure that it can't be easily subverted by changing any one single 
  348. instruction. Program defensively. Check often for licence violations. 
  349. Duplicate all the "check" code if necessary, so that the subversion of 
  350. a single routine will not sucessfully crack the system. If the cracker
  351. has to simultaneously modify three or more instructions/variables, cracking
  352. is significantly harder.
  353.  
  354.  
  355.  
  356. Certainly it is impossible to make your system unbreakable. Consider
  357. in all of the above, a somewhat experienced hacker could crack the
  358. system in less than four hours. The goal of the implementor should
  359. be to design the licensing components in a sufficiently convoluted
  360. way so that much more effort is needed.
  361.  
  362.  
  363. Appendix.
  364.  
  365. Unstrip for Sun 4/sun os 4.1.1
  366.  
  367.  
  368. From: pk@cs.few.eur.nl (Paul Kranenburg)
  369. Newsgroups: alt.sources
  370. Subject: unstrip a stripped dynamically linked executable.
  371. Keywords: dynamic linking, debugging
  372. Message-ID: <1992Jan22.161325.22872@cs.few.eur.nl>
  373. Date: 22 Jan 92 16:13:25 GMT
  374. Sender: news@cs.few.eur.nl
  375. Reply-To: pk@cs.eur.nl
  376. Organization: Erasmus University Rotterdam
  377. Lines: 1319
  378.  
  379. Ever found the odd core file lying around in your root directory
  380. and discovered that it was dropped by some system supplied daemon
  381. which didn't even contained a name list?
  382.  
  383. If this happens on SunOS 4.x system (and it certainly does happen on
  384. ours) and the executable is dynamically linked (as most of them are)
  385. you may at least be able to get a decent traceback with adb(1)
  386. after forcing the necessary symbolic information into the open
  387. again.
  388.  
  389. This is the purpose of the enclosed programme, which takes advantage
  390. of the fact that the run-time linker (ld.so) needs the same symbolic
  391. information to perform its task and is therefore included in
  392. the executable's text segment by its companion, ld(1).
  393.  
  394. Quote from README:
  395.  
  396. "Information for the run-time linker is stored in an executable's text
  397. and data segment. This includes a symbol- and string table in standard
  398. (a.out) format. Careful examination of the <link.h> header file and
  399. tracing of some simple dynamically linked programs reveal the intrinsics
  400. of the run-time link process, enabling the extraction of the symbol
  401. table and putting it back on the spot where it used to be before
  402. the executable was stripped."
  403.  
  404.  
  405. Cheers, Paul.
  406.  
  407. - -------------------------------------------------------------------------
  408. #! /bin/sh
  409. # This is a shell archive.  Remove anything before this line, then unpack
  410. # it by saving it into a file and typing "sh file".  To overwrite existing
  411. # files, type "sh file -c".  You can also feed this as standard input via
  412. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  413. # will see the following message at the end:
  414. #       "End of archive 1 (of 1)."
  415. # Contents:  Makefile README defs.h nm.c nmd.1 unstrip.1 unstrip.c
  416. #   util.c
  417. # Wrapped by pk@kaa on Wed Jan 22 16:35:51 1992
  418. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  419. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  420.   echo shar: Will not clobber existing file \"'Makefile'\"
  421. else
  422. echo shar: Extracting \"'Makefile'\" \(746 characters\)
  423. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  424. X#
  425. X# @(#)Makefile 1.2 92/01/22
  426. X#
  427. XBINDIR=/usr/local/bin
  428. XMANDIR=/usr/local/man/man1
  429. XCC=cc
  430. XCFLAGS=-O
  431. XOBJS=util.o
  432. XKIT=   Makefile README unstrip.1 nmd.1 defs.h util.c unstrip.c nm.c
  433. X
  434. Xall: nm unstrip
  435. X
  436. Xnm: nm.o $(OBJS)
  437. X   $(CC) $(CFLAGS) -o $@ nm.o $(OBJS)
  438. X
  439. Xunstrip: unstrip.o $(OBJS)
  440. X   $(CC) $(CFLAGS) -o $@ unstrip.o $(OBJS)
  441. X
  442. Xd2o: d2o.o $(OBJS)
  443. X   $(CC) $(CFLAGS) -o $@ d2o.o $(OBJS)
  444. X
  445. Xinstall: nm unstrip
  446. X   install -m 555 nm $(BINDIR)/nmd
  447. X   install -m 555 unstrip $(BINDIR)
  448. X
  449. Xinstall.man: unstrip.1 nmd.1
  450. X   install -m 444 unstrip.1 $(MANDIR)
  451. X   install -m 444 nmd.1 $(MANDIR)
  452. X
  453. Xclean:
  454. X   rm -f *.o a.out core nm unstrip d2o Part?? nm.tar.Z
  455. X
  456. Xkit: $(KIT)
  457. X   makekit $(KIT)
  458. X
  459. Xtar: $(KIT)
  460. X   tar cf - $(KIT) | compress > nm.tar.Z
  461. X
  462. Xnm.o: defs.h
  463. Xunstrip.o: defs.h
  464. Xd2o.o: defs.h
  465. END_OF_FILE
  466. if test 746 -ne `wc -c <'Makefile'`; then
  467.     echo shar: \"'Makefile'\" unpacked with wrong size!
  468. fi
  469. # end of 'Makefile'
  470. fi
  471. if test -f 'README' -a "${1}" != "-c" ; then 
  472.   echo shar: Will not clobber existing file \"'README'\"
  473. else
  474. echo shar: Extracting \"'README'\" \(1634 characters\)
  475. sed "s/^X//" >'README' <<'END_OF_FILE'
  476. X@(#)README 1.2 92/01/22
  477. X
  478. Xunstrip - restore symbols and relocation bits in a dynamically
  479. X     linked object file
  480. X
  481. Xnmd    - a nm(1) like programme that is capable of showing the name
  482. X     list and relocation information of dynamically linked executables
  483. X
  484. X
  485. XInformation for the run-time linker is stored in an executable's text
  486. Xand data segment. This includes a symbol- and string table in standard
  487. X(a.out) format. Careful examination of the <link.h> header file and
  488. Xtracing of some simple dynamically linked programs reveal the intrinsics
  489. Xof the run-time link process, enabling the extraction of the symbol
  490. Xtable and putting it back on the spot where it used to be before
  491. Xthe executable was stripped.
  492. X
  493. XFortunately, the "internal" symbol table still includes entries
  494. Xof symbols that were already resolved by the static linking process,
  495. Xprovided they carry the "external" attribute.
  496. X
  497. XThe mechanisms employed by the dynamic linker have been declared
  498. Xvolatile by Sun (cf. link(5)), so these programs may stop working
  499. Xat any moment (perhaps even without upgrading your OS :-).
  500. X
  501. XHowever, the SVR4 SPARC ABI specifies many items related to dynamic
  502. Xlinking and also documents the relocation types which are nowhere to
  503. Xbe found in SunOS 4.1.x documentation (most notably the RELOC_JMP_SLOT
  504. Xtype that appears to define the relation of a symbol to the Procedure
  505. XLinkage Table). If this extrapolates to SunOS 4.1.x, some hacks in
  506. Xthese programs could be cleaned up.
  507. X
  508. XA makefile and two quick manual pages are included in this distribution.
  509. X
  510. X
  511. XAuthor:
  512. X
  513. X   P.Kranenburg
  514. X   Deptartment of Computer Science
  515. X   Erasmus University Rotterdam (NL)
  516. X   email: pk@cs.few.eur.nl
  517. END_OF_FILE
  518. if test 1634 -ne `wc -c <'README'`; then
  519.     echo shar: \"'README'\" unpacked with wrong size!
  520. fi
  521. # end of 'README'
  522. fi
  523. if test -f 'defs.h' -a "${1}" != "-c" ; then 
  524.   echo shar: Will not clobber existing file \"'defs.h'\"
  525. else
  526. echo shar: Extracting \"'defs.h'\" \(764 characters\)
  527. sed "s/^X//" >'defs.h' <<'END_OF_FILE'
  528. X/*
  529. X * @(#)defs.h  1.2 92/01/22
  530. X */
  531. X
  532. Xstruct execmap {
  533. X   struct exec *e_hdr;         /* exec header */
  534. X   caddr_t     e_text;         /* text segment */
  535. X   caddr_t     e_data;         /* data segment */
  536. X   struct nlist    *e_nlist;       /* symbol table */
  537. X   int     e_nnlist;       /* # of nlist */
  538. X#ifdef sparc
  539. X#define reloc_info reloc_info_sparc
  540. X#endif
  541. X#ifdef mc68000
  542. X#define reloc_info reloc_info_68k
  543. X#endif
  544. X   struct reloc_info   *e_trel;    /* relocation tables */
  545. X   struct reloc_info   *e_drel;
  546. X   int     e_ntrel;        /* # of text relocations */
  547. X   int     e_ndrel;        /* # of data relocations */
  548. X   char        *e_sym;         /* string table */
  549. X#ifdef sun
  550. X   int     e_mlen;         /* size of mapped object */
  551. X#endif
  552. X};
  553. X
  554. Xstruct execmap *mapfile();
  555. Xint unmapfile();
  556. Xvoid prtsym(), prthdr(), prtrel();
  557. Xint ncompare(), scompare(), rncompare(), rscompare();
  558. END_OF_FILE
  559. if test 764 -ne `wc -c <'defs.h'`; then
  560.     echo shar: \"'defs.h'\" unpacked with wrong size!
  561. fi
  562. # end of 'defs.h'
  563. fi
  564. if test -f 'nm.c' -a "${1}" != "-c" ; then 
  565.   echo shar: Will not clobber existing file \"'nm.c'\"
  566. else
  567. echo shar: Extracting \"'nm.c'\" \(5881 characters\)
  568. sed "s/^X//" >'nm.c' <<'END_OF_FILE'
  569. X/*
  570. X * @(#)nm.c    1.2 92/01/22    - display an a.out symbol table
  571. X */
  572. X
  573. X#include <stdio.h>
  574. X#include <sys/types.h>
  575. X#include <a.out.h>
  576. X#ifndef sun
  577. X#include <nlist.h>
  578. X#endif
  579. X#ifdef sun
  580. X#include <link.h>
  581. X#endif
  582. X#include "defs.h"
  583. X
  584. Xextern char *malloc();
  585. X
  586. Xstatic aflag, dflag, gflag, hflag, nflag, pflag, rflag, uflag, xflag;
  587. X
  588. Xmain(argc, argv)
  589. Xint argc;
  590. Xchar *argv[];
  591. X{
  592. X   int c, status = 0;
  593. X   extern int optind;
  594. X   extern char *optarg;
  595. X
  596. X   while ((c = getopt(argc, argv, "adghnprux")) != EOF) {
  597. X       switch (c) {
  598. X       case 'a':
  599. X           aflag++;
  600. X           break;
  601. X       case 'n':
  602. X           nflag++;
  603. X           break;
  604. X       case 'p':
  605. X           pflag++;
  606. X           break;
  607. X       case 'h':
  608. X           hflag++;
  609. X           break;
  610. X       case 'r':
  611. X           rflag++;
  612. X           break;
  613. X       case 'u':
  614. X           uflag++;
  615. X           break;
  616. X       case 'g':
  617. X           gflag++;
  618. X           break;
  619. X       case 'x':
  620. X           xflag++;
  621. X           break;
  622. X#ifdef sun
  623. X       case 'd':
  624. X           dflag++;
  625. X           break;
  626. X#endif
  627. X       default:
  628. X           fprintf(stderr, "Usage: %s file ...\n", argv[0]);
  629. X           return -1;
  630. X           break;
  631. X       }
  632. X   }
  633. X   if (argc <= optind) {
  634. X       status = nm("a.out") == -1;
  635. X   } else if (argc == optind + 1) {
  636. X       status = nm(argv[optind]) == -1;
  637. X   } else {
  638. X       for (; optind < argc; optind++) {
  639. X           printf("\n%s:\n", argv[optind]);
  640. X           status |= nm(argv[optind]) == -1;
  641. X       }
  642. X   }
  643. X   return status;
  644. X}
  645. X
  646. Xnm(file)
  647. Xchar *file;
  648. X{
  649. X   int fd;
  650. X   struct exec *hp;
  651. X   struct execmap *mp;
  652. X
  653. X   if ((mp = mapfile(file)) == NULL) {
  654. X       return -1;
  655. X   }
  656. X   hp = mp->e_hdr;
  657. X   if (hflag || aflag) {
  658. X       prthdr(hp);
  659. X       if (!aflag) return 0;
  660. X   }
  661. X   if (hp->a_syms == 0 && !dflag) {
  662. X       fprintf(stderr, "%s: no name list\n", file);
  663. X       return -1;
  664. X   }
  665. X   if (hp->a_syms != 0 && (aflag || !dflag))
  666. X       prtnlist(mp, aflag);
  667. X
  668. X   if (aflag || xflag) {
  669. X       if (hp->a_trsize + hp->a_drsize != 0) {
  670. X           prtarel(mp);
  671. X       } else if (!aflag) {
  672. X           fprintf(stderr, "%s: no relocation\n", file);
  673. X           return -1;
  674. X       }
  675. X   }
  676. X#ifdef sun
  677. X   if (dflag || aflag)
  678. X       prtdyn(mp);
  679. X#endif
  680. X
  681. X   unmapfile(mp);
  682. X   return 0;
  683. X}
  684. X
  685. Xint
  686. Xprtnlist(mp)
  687. Xstruct execmap *mp;
  688. X{
  689. X   int n;
  690. X   struct nlist *nlp;
  691. X
  692. X   n = mp->e_nnlist;
  693. X   nlp = mp->e_nlist;
  694. X   if (!pflag) {
  695. X       nlp = (struct nlist *)malloc(n * sizeof(struct nlist));
  696. X       bcopy((char *)mp->e_nlist, (char *)nlp, n*sizeof(struct nlist));
  697. X       qsort((char *)nlp, n, sizeof(struct nlist),
  698. X               nflag?
  699. X                   (rflag?rncompare:ncompare)
  700. X               :
  701. X                   (rflag?rscompare:scompare));
  702. X   }
  703. X   for(; n; n--, nlp++) {
  704. X       if (aflag ||
  705. X           ((nlp->n_type & N_STAB) == 0 && (
  706. X               (!gflag && !uflag) ||
  707. X               (uflag && (nlp->n_type & N_TYPE) == N_UNDF) ||
  708. X               (gflag && (nlp->n_type & N_EXT))
  709. X               )
  710. X           )
  711. X       ) {
  712. X           prtsym(nlp);
  713. X           fputc('\n', stdout);
  714. X       }
  715. X   }
  716. X   return 0;
  717. X}
  718. X
  719. Xprtarel(mp)
  720. Xstruct execmap *mp;
  721. X{
  722. X#ifdef sun
  723. X   if (mp->e_hdr->a_trsize) {
  724. X       printf("\nText relocations:\n");
  725. X       prtrel(mp->e_trel, mp->e_ntrel, mp->e_nlist);
  726. X   }
  727. X   if (mp->e_hdr->a_drsize) {
  728. X       printf("\nData relocations:\n");
  729. X       prtrel(mp->e_drel, mp->e_ndrel, mp->e_nlist);
  730. X   }
  731. X#else
  732. X   fprintf(stderr, "\nrelocations not done\n");
  733. X#endif
  734. X}
  735. X
  736. X#ifdef sun
  737. Xint
  738. Xprtdyn(mp)
  739. Xstruct execmap *mp;
  740. X{
  741. X   struct link_dynamic *dynp;
  742. X   struct link_dynamic_2 *ldp;
  743. X   struct ld_debug *lddp;
  744. X   struct link_object *lop = NULL;
  745. X   char *d_rules = NULL;
  746. X   struct nlist *nlp;
  747. X   int i, nnlist, nrel, nplt, ngot;
  748. X   char *strtab;
  749. X   struct reloc_info *rlp;
  750. X   long *got;
  751. X   struct plt {
  752. X       int X1, X2, X3;
  753. X   } *plt;
  754. X
  755. X   if (!mp->e_hdr->a_dynamic) {
  756. X       fprintf(stderr, "Not dynamic\n");
  757. X       return -1;
  758. X   }
  759. X   /* By convention, __DYNAMIC is first data item */
  760. X   dynp = (struct link_dynamic *)mp->e_data;
  761. X   /*
  762. X    * Various tables and structures are imbedded in text and data segment
  763. X    * In text: relocation table, hash table, stab table, string table,
  764. X    *      needed link_objects, library search rules
  765. X    * In data: link_dynamic[-2], debugger iface, global offset table,
  766. X    *      procedure linkage table
  767. X    */
  768. X    /* First, some relocations of our own */
  769. X   ldp = (struct link_dynamic_2 *)
  770. X       ((long)dynp->ld_un.ld_2 - N_DATADDR(*(mp->e_hdr)) + (long)mp->e_data);
  771. X   lddp = (struct ld_debug *)
  772. X       ((long)dynp->ldd - N_DATADDR(*(mp->e_hdr)) + (long)mp->e_data) ;
  773. X   if (ldp->ld_need)
  774. X       lop = (struct link_object *)(ldp->ld_need + mp->e_text);
  775. X   if (ldp->ld_rules)
  776. X       d_rules = (char *)(ldp->ld_rules + (long)mp->e_text);
  777. X   got = (long *)(ldp->ld_got - N_DATADDR(*(mp->e_hdr)) + (long)mp->e_data);
  778. X   ngot = (ldp->ld_plt - ldp->ld_got) / sizeof(long);
  779. X
  780. X   plt = (struct plt *)(ldp->ld_plt - N_DATADDR(*(mp->e_hdr)) + (long)mp->e_data);
  781. X   nplt = ldp->ld_plt_sz / sizeof(struct plt);
  782. X
  783. X   rlp = (struct reloc_info *)(ldp->ld_rel + (long)mp->e_text);
  784. X   nrel = (ldp->ld_hash - ldp->ld_rel) / sizeof(struct reloc_info);
  785. X
  786. X   nlp = (struct nlist *)(ldp->ld_stab + (long)mp->e_text);
  787. X   nnlist = (ldp->ld_symbols - ldp->ld_stab) / sizeof(struct nlist);
  788. X   strtab = (char *)((long)mp->e_text + ldp->ld_symbols);
  789. X   for (i = 0; i < nnlist; i++) {
  790. X       if (nlp[i].n_un.n_strx < ldp->ld_symb_size)
  791. X           nlp[i].n_un.n_name = strtab + nlp[i].n_un.n_strx;
  792. X       else
  793. X           nlp[i].n_un.n_name = "sym_???";
  794. X   }
  795. X
  796. X   printf("Dynamic name list (%u):\n", nnlist);
  797. X   for(i = 0; i < nnlist; i++) {
  798. X       prtsym(&nlp[i]);
  799. X       fputc('\n', stdout);
  800. X   }
  801. X
  802. X   printf("\nProcedure linkage table (%u):\n", nplt);
  803. X   printf(" PLT  GOT  DYN\n");
  804. X   /* first entry in the plt contains entry point for ld.so */
  805. X   for(i = 1; i < nplt; i++) {
  806. X       printf("%4x %4x %4x ", i*sizeof(struct plt),
  807. X           i*sizeof(struct plt) + (char *)plt - (char *)got,
  808. X           i*sizeof(struct plt) + (char *)plt - (char *)dynp);
  809. X       prtrel(&rlp[(plt[i].X3 & 0xffff)], 1, nlp);
  810. X   }
  811. X
  812. X   printf("\nGlobal offset table (%u):\n", ngot);
  813. X   for(i = 0; i < ngot; i++) {
  814. X       printf(" [got entry: %x]\n", got[i]);
  815. X   }
  816. X
  817. X   if (aflag || xflag) {
  818. X       printf("\nDynamic relocations (%u):\n", nrel);
  819. X       prtrel(rlp, nrel, nlp);
  820. X   }
  821. X
  822. X   if (lop) {
  823. X       printf("\nNeeded libs:\n");
  824. X       while (1) {
  825. X           if (lop->lo_library)
  826. X               printf("\tlib%s.so.%u.%u (SEARCHED)\n",
  827. X                   lop->lo_name + mp->e_text,
  828. X                   lop->lo_major, lop->lo_minor);
  829. X           else
  830. X               printf("\t%s\n", lop->lo_name + mp->e_text);
  831. X           if (lop->lo_next == 0)
  832. X               break;
  833. X           lop = (struct link_object *)(lop->lo_next + mp->e_text);
  834. X       }
  835. X   }
  836. X   if (d_rules)
  837. X       printf("Search rules: %s\n", d_rules);
  838. X   return 0;
  839. X}
  840. X#endif
  841. END_OF_FILE
  842. if test 5881 -ne `wc -c <'nm.c'`; then
  843.     echo shar: \"'nm.c'\" unpacked with wrong size!
  844. fi
  845. # end of 'nm.c'
  846. fi
  847. if test -f 'nmd.1' -a "${1}" != "-c" ; then 
  848.   echo shar: Will not clobber existing file \"'nmd.1'\"
  849. else
  850. echo shar: Extracting \"'nmd.1'\" \(1966 characters\)
  851. sed "s/^X//" >'nmd.1' <<'END_OF_FILE'
  852. X.\" @(#)nmd.1  1.1 92/01/22
  853. X.TH NMD 1 "January 1992"
  854. X.SH NAME
  855. Xnmd \- print symbol name list
  856. X.SH SYNOPSIS
  857. X.B nmd
  858. X[
  859. X.B \-dgnpruxa
  860. X]
  861. X[
  862. X.RI [ " filename " "] .\|.\|."
  863. X.SH DESCRIPTION
  864. X.IX  "nmd command"  ""  "\fLnmd\fP \(em display name list"
  865. X.IX  display "name list of object file or library \(em \fLnmd\fP"
  866. X.IX  "programming tools"  nmd  ""  "\fLnm\fP \(em display name list"
  867. X.B nmd
  868. Xprints the name list (symbol table) of each object
  869. X.I filename
  870. Xin the argument list.
  871. XIf no
  872. X.I filename
  873. Xis given, the symbols in
  874. X.B a.out
  875. Xare listed.
  876. X.SS Output Format
  877. X.LP
  878. XEach symbol name is preceded by its value (blanks if undefined)
  879. Xand one of the letters:
  880. X.TP
  881. X.B A
  882. Xabsolute
  883. X.TP
  884. X.B B
  885. Xbss segment symbol
  886. X.TP
  887. X.B C
  888. Xcommon symbol
  889. X.TP
  890. X.B D
  891. Xdata segment symbol
  892. X.TP
  893. X.B f
  894. Xfilename
  895. X.TP
  896. X.B t
  897. Xa static function symbol
  898. X.TP
  899. X.B  T
  900. Xtext segment symbol
  901. X.TP
  902. X.B U
  903. Xundefined
  904. X.TP
  905. X.B \-
  906. Xdebug, giving symbol table entries (see
  907. X.B \-a
  908. Xbelow)
  909. X.LP
  910. XThe type letter is upper case if the symbol is external, and
  911. Xlower case if it is local.  The output is sorted alphabetically.
  912. X.SH OPTIONS
  913. X.TP
  914. X.B  \-a
  915. XPrint all symbols.
  916. X.TP
  917. X.B  \-d
  918. XPrint dynamic linker information. This includes
  919. Xthe name list and Procedure Linkage Table entries.
  920. X.TP
  921. X.B  \-g
  922. XPrint only global (external) symbols.
  923. X.TP
  924. X.B \-n
  925. XSort numerically rather than alphabetically.
  926. X.TP
  927. X.B  \-o
  928. XPrepend file or archive element name to
  929. Xeach output line rather than only once.
  930. X.TP
  931. X.B  \-p
  932. XDo not sort; print in symbol-table order.
  933. X.TP
  934. X.B  \-r
  935. XSort in reverse order.
  936. X.TP
  937. X.B  \-x
  938. XPrint relocation tables.
  939. X.TP
  940. X.B  \-u
  941. XPrint only undefined symbols.
  942. X.SH EXAMPLE
  943. X.IP
  944. X.B example% nmd
  945. X.LP
  946. Xprints the symbol list of the file named
  947. X.BR  a.out ,
  948. Xthe default output file for the
  949. X.BR C ,
  950. Xcompiler.
  951. X.SH SEE ALSO
  952. X.BR as (1),
  953. X.BR cc (1V),
  954. X.BR ld (1),
  955. X.BR a.out (5),
  956. X.SH BUGS
  957. X.LP
  958. XArchive files (see ar(1)) are not supported.
  959. X.LP
  960. XPrinting of relocation tables is not complete.
  961. X.LP
  962. XThe
  963. X.B \-g,
  964. X.B \-u,
  965. X.B \-n,
  966. Xand
  967. X.B \-r
  968. Xoptions do not apply when the
  969. X.B \-d
  970. Xoption is in effect.
  971. END_OF_FILE
  972. if test 1966 -ne `wc -c <'nmd.1'`; then
  973.     echo shar: \"'nmd.1'\" unpacked with wrong size!
  974. fi
  975. # end of 'nmd.1'
  976. fi
  977. if test -f 'unstrip.1' -a "${1}" != "-c" ; then 
  978.   echo shar: Will not clobber existing file \"'unstrip.1'\"
  979. else
  980. echo shar: Extracting \"'unstrip.1'\" \(1386 characters\)
  981. sed "s/^X//" >'unstrip.1' <<'END_OF_FILE'
  982. X.\" @(#)unstrip.1  1.2 92/01/22
  983. X.TH UNSTRIP 1 "January 1992"
  984. X.SH NAME
  985. Xunstrip \- restore symbols and relocation bits in a dynamically linked object file
  986. X.SH SYNOPSIS
  987. X.B unstrip [-h] [-n] [-r]
  988. X.IR filename .\|.\|.
  989. X.SH DESCRIPTION
  990. X.IX  "unstrip command"  ""  "\fLunstrip\fP \(em restore symbols and relocation bits"
  991. X.IX  "programming tools"  strip  ""  "\fLstrip\fP \(em restore symbols and relocation bits"
  992. X.IX  "object file"  strip  ""  "\fLstrip\fP \(em restore symbols and relocation bits"
  993. X.LP
  994. X.B unstrip
  995. Xexternalizes the symbol
  996. Xtable and relocation bits ordinarily provided by the linker
  997. Xin the data segment of a dynamically linked executable.
  998. XThis is useful to debug a program after a it has been stripped to save space.
  999. X.LP
  1000. X.B unstrip
  1001. Xfixes up the symbol table for the benefit of
  1002. X.B adb
  1003. Xin such a way as to show calls to functions in shared
  1004. Xobjects symbolically (eg. ``call printf'') as opposed to
  1005. Xindirections through the Procedure Linkage Table
  1006. X(such as ``call __DYNAMIC + 0x1234'').
  1007. X.SH OPTIONS
  1008. X.TP
  1009. X.BI \-h
  1010. XShow header information of newly created object file.
  1011. X.TP
  1012. X.BI \-n
  1013. XDo not fix up symbol table (leaves functions in shared objects show
  1014. Xas ``undefined'' when viewed with
  1015. X.BR nm (1)).
  1016. X.TP
  1017. X.BI \-r
  1018. XDo not pull up relocation information.
  1019. X.SH SEE ALSO
  1020. X.BR ld (1),
  1021. X.BR adb (1),
  1022. X.BR strip (1),
  1023. X.BR nm (1),
  1024. X.BR a.out (5),
  1025. X.BR link (5)
  1026. X.SH BUGS
  1027. X.LP
  1028. XOverwrites existing symbol table.
  1029. END_OF_FILE
  1030. if test 1386 -ne `wc -c <'unstrip.1'`; then
  1031.     echo shar: \"'unstrip.1'\" unpacked with wrong size!
  1032. fi
  1033. # end of 'unstrip.1'
  1034. fi
  1035. if test -f 'unstrip.c' -a "${1}" != "-c" ; then 
  1036.   echo shar: Will not clobber existing file \"'unstrip.c'\"
  1037. else
  1038. echo shar: Extracting \"'unstrip.c'\" \(6328 characters\)
  1039. sed "s/^X//" >'unstrip.c' <<'END_OF_FILE'
  1040. X/*
  1041. X * @(#)unstrip.c   1.2 92/01/22    - put symbol table of stripped dynamically linked a.out back into place
  1042. X */
  1043. X
  1044. X#include <stdio.h>
  1045. X#include <sys/types.h>
  1046. X#include <string.h>
  1047. X#include <fcntl.h>
  1048. X#include <a.out.h>
  1049. X#include <sys/stat.h>
  1050. X#include <link.h>
  1051. X#include "defs.h"
  1052. X
  1053. Xextern char *malloc();
  1054. X
  1055. Xstatic hflag, nflag, rflag;
  1056. Xstruct execmap *makesymbols();
  1057. X
  1058. Xmain(argc, argv)
  1059. Xchar *argv[];
  1060. X{
  1061. X   int c, status = 0;
  1062. X   extern int optind;
  1063. X   extern char *optarg;
  1064. X
  1065. X   while ((c = getopt(argc, argv, "hnr")) != EOF) {
  1066. X       switch (c) {
  1067. X       case 'n':
  1068. X           nflag++;
  1069. X           break;
  1070. X       case 'h':
  1071. X           hflag++;
  1072. X           break;
  1073. X       case 'r':
  1074. X           rflag++;
  1075. X           break;
  1076. X       default:
  1077. X           fprintf(stderr, "Usage: %s [file ...]\n", argv[0]);
  1078. X           return -1;
  1079. X           break;
  1080. X       }
  1081. X   }
  1082. X   if (argc <= optind) {
  1083. X       status = unstrip("a.out") == -1;
  1084. X   } else if (argc == optind + 1) {
  1085. X       status = unstrip(argv[optind]) == -1;
  1086. X   } else {
  1087. X       for (; optind < argc; optind++) {
  1088. X           printf("\n%s:\n", argv[optind]);
  1089. X           status |= unstrip(argv[optind]) == -1;
  1090. X       }
  1091. X   }
  1092. X   return status;
  1093. X}
  1094. X
  1095. Xint
  1096. Xunstrip(file)
  1097. Xchar *file;
  1098. X{
  1099. X   int fd, res;
  1100. X   struct exec *hp;
  1101. X   struct execmap *mp, *nmp;
  1102. X
  1103. X   if ((mp = mapfile(file)) == NULL) {
  1104. X       return -1;
  1105. X   }
  1106. X   hp = mp->e_hdr;
  1107. X   if (!hp->a_dynamic) {
  1108. X       fprintf(stderr, "%s: Not dynamic\n", file);
  1109. X       (void)unmapfile(mp);
  1110. X       return -1;
  1111. X   }
  1112. X   if (hp->a_trsize != 0 || hp->a_drsize != 0) {
  1113. X       fprintf(stderr, "Warning: %s contains relocation table\n", file);
  1114. X       (void)unmapfile(mp);
  1115. X       return -1;
  1116. X   }
  1117. X   if ((nmp = makesymbols(mp)) == NULL) {
  1118. X       fprintf(stderr, "Couldn't get symbols from %s\n", file);
  1119. X       (void)unmapfile(mp);
  1120. X       return -1;
  1121. X   }
  1122. X   if ((fd = open(file, O_WRONLY|O_CREAT, 0666)) == -1) {
  1123. X       perror("open");
  1124. X       res = -1;
  1125. X       goto quit;
  1126. X   }
  1127. X
  1128. X   if (writemap(fd, nmp) < 0 || close(fd) < 0) {
  1129. X       perror("writemap");
  1130. X       res = -1;
  1131. X       goto quit;
  1132. X   }
  1133. X   res = 0;
  1134. X
  1135. X   if (hflag)
  1136. X       prthdr(nmp->e_hdr);
  1137. X
  1138. Xquit:
  1139. X   if (nmp->e_nlist) (void)free((char *)nmp->e_nlist);
  1140. X   if (nmp->e_sym) (void)free((char *)nmp->e_sym);
  1141. X   if (nmp->e_trel) (void)free((char *)nmp->e_trel);
  1142. X#if 0
  1143. X   (void)free((char *)nmp->e_hdr);
  1144. X#endif
  1145. X   (void)free((char *)nmp);
  1146. X   if (unmapfile(mp) < 0)
  1147. X       return -1;;
  1148. X   return res;
  1149. X}
  1150. X
  1151. Xint
  1152. Xwritemap(fd, mp)
  1153. Xstruct execmap *mp;
  1154. X{
  1155. X   struct exec *hp = mp->e_hdr;
  1156. X   unsigned long n;
  1157. X
  1158. X   if (write(fd, (char *)hp, sizeof(*hp)) < sizeof(*hp))
  1159. X       return -1;
  1160. X
  1161. X   if (lseek(fd, hp->a_text + hp->a_data + N_TXTOFF(*hp), 0) < 0)
  1162. X       return -1;
  1163. X
  1164. X   if (hp->a_trsize &&
  1165. X       write(fd, (char *)mp->e_trel, hp->a_trsize) < hp->a_trsize)
  1166. X       return -1;
  1167. X
  1168. X   if (hp->a_drsize &&
  1169. X       write(fd, (char *)mp->e_drel, hp->a_drsize) < hp->a_drsize)
  1170. X       return -1;
  1171. X
  1172. X   if (write(fd, (char *)mp->e_nlist, hp->a_syms) < hp->a_syms)
  1173. X       return -1;
  1174. X
  1175. X   bcopy(mp->e_sym, (char *)&n, sizeof n);
  1176. X   if (write(fd, mp->e_sym, n) < n)
  1177. X       return -1;
  1178. X
  1179. X   return 0;
  1180. X}
  1181. X
  1182. Xstruct execmap *
  1183. Xmakesymbols(mp)
  1184. Xstruct execmap *mp;
  1185. X{
  1186. X   struct execmap *nmp;
  1187. X   struct link_dynamic *dynp;
  1188. X   struct link_dynamic_2 *ldp;
  1189. X   struct ld_debug *lddp;
  1190. X   struct link_object *lop;
  1191. X   char *d_rules;
  1192. X   struct nlist *nlp;
  1193. X   char *strtab;
  1194. X   int i, nnlist, nrel, nplt, ngot;
  1195. X   struct reloc_info *rlp;
  1196. X   long *got;
  1197. X   struct plt {
  1198. X       int X1, X2, X3;
  1199. X   } *plt;
  1200. X
  1201. X   /* By convention, __DYNAMIC is first data item */
  1202. X   dynp = (struct link_dynamic *)mp->e_data;
  1203. X   /*
  1204. X    * Various tables and structures are imbedded in text and data segment
  1205. X    * In text: relocation table, hash table, stab table, string table
  1206. X    * In data: link_dynamic[_2], debugger iface, global offset table,
  1207. X    *      procedure linkage table
  1208. X    */
  1209. X    /* First, some relocations of our own */
  1210. X   ldp = (struct link_dynamic_2 *)
  1211. X       ((long)dynp->ld_un.ld_2 - N_DATADDR(*(mp->e_hdr)) + (long)mp->e_data);
  1212. X   lddp = (struct ld_debug *)
  1213. X       ((long)dynp->ldd - N_DATADDR(*(mp->e_hdr)) + (long)mp->e_data) ;
  1214. X   lop = (struct link_object *)(ldp->ld_need + mp->e_text);
  1215. X   d_rules = (char *)(ldp->ld_rules + (long)mp->e_text);
  1216. X   got = (long *)(ldp->ld_got - N_DATADDR(*(mp->e_hdr)) + (long)mp->e_data);
  1217. X   ngot = (ldp->ld_plt - ldp->ld_got) / sizeof(long);
  1218. X
  1219. X   plt = (struct plt *)(ldp->ld_plt - N_DATADDR(*(mp->e_hdr)) + (long)mp->e_data);
  1220. X   nplt = ldp->ld_plt_sz / sizeof(struct plt);
  1221. X
  1222. X   rlp = (struct reloc_info *)(ldp->ld_rel + (long)mp->e_text);
  1223. X   nrel = (ldp->ld_hash - ldp->ld_rel) / sizeof(struct reloc_info);
  1224. X
  1225. X   nlp = (struct nlist *)(ldp->ld_stab + (long)mp->e_text);
  1226. X   nnlist = (ldp->ld_symbols - ldp->ld_stab) / sizeof(struct nlist);
  1227. X   strtab = (char *)((long)mp->e_text + ldp->ld_symbols);
  1228. X
  1229. X   /* allocate new map */
  1230. X   if ((nmp = (struct execmap *)calloc(1, sizeof(*nmp))) == NULL) {
  1231. X       fprintf(stderr, "No memory\n");
  1232. X       return NULL;
  1233. X   }
  1234. X   /* allocate new stab, symbol and reloc tables */
  1235. X   nmp->e_nlist = (struct nlist *)malloc(ldp->ld_symbols - ldp->ld_stab);
  1236. X
  1237. X   if (nmp->e_nlist == NULL) {
  1238. X       fprintf(stderr, "Out of memory\n");
  1239. X       return NULL;
  1240. X   }
  1241. X   bcopy((char *)nlp, (char *)nmp->e_nlist, ldp->ld_symbols - ldp->ld_stab);
  1242. X
  1243. X   for(i = 0; i < nnlist; i++) {
  1244. X       /* Fix up sym index */
  1245. X       nmp->e_nlist[i].n_un.n_strx += 4;
  1246. X   }
  1247. X   nmp->e_sym = malloc(ldp->ld_symb_size + 4);
  1248. X   if (nmp->e_sym == NULL) {
  1249. X       fprintf(stderr, "Out of memory\n");
  1250. X       return NULL;
  1251. X   }
  1252. X   *(long *)nmp->e_sym = ldp->ld_symb_size + 4;
  1253. X   bcopy(strtab, nmp->e_sym + 4, ldp->ld_symb_size);
  1254. X
  1255. X   nmp->e_trel = (struct reloc_info *)malloc((nplt-1)*sizeof(struct reloc_info));
  1256. X   if (nmp->e_trel == NULL) {
  1257. X       fprintf(stderr, "Out of memory\n");
  1258. X       return NULL;
  1259. X   }
  1260. X   /* first entry in the plt contains entry point for ld.so */
  1261. X   for(i = 1; i < nplt; i++) {
  1262. X       bcopy((char *)&rlp[(plt[i].X3 & 0xffff)],
  1263. X           (char *)&nmp->e_trel[i-1], sizeof(struct reloc_info));
  1264. X   }
  1265. X
  1266. X   /* Fix up nlist for adb */
  1267. X   if (!nflag)
  1268. X       for(i = 1; i < nplt; i++) {
  1269. X           struct reloc_info *rp = &rlp[(plt[i].X3 & 0xffff)];
  1270. X           struct nlist *np;
  1271. X
  1272. X           if (rp->r_extern == 0) {
  1273. X               fprintf(stderr, "Weird reloc\n");
  1274. X               continue;
  1275. X           }
  1276. X           np = &nmp->e_nlist[rp->r_index];
  1277. X           np->n_value = ldp->ld_plt + i*sizeof(*plt);
  1278. X           np->n_type = N_TEXT | (np->n_type & N_EXT);
  1279. X       }
  1280. X
  1281. X#if 0
  1282. X   if ((nmp->e_hdr = (struct exec *)calloc(1, sizeof *nmp->e_hdr)) == NULL) {
  1283. X       fprintf(stderr, "Out of memory\n");
  1284. X       return NULL;
  1285. X   }
  1286. X#endif
  1287. X   nmp->e_hdr = mp->e_hdr;
  1288. X
  1289. X   /* copy header, text, data and bss from old map */
  1290. X   nmp->e_text = mp->e_text;
  1291. X   nmp->e_data = mp->e_data;
  1292. X
  1293. X   /* Add symbols to a.out header */
  1294. X   nmp->e_hdr->a_syms = nnlist*sizeof(struct nlist);
  1295. X   if (rflag)
  1296. X       nmp->e_hdr->a_trsize = (nplt-1)*sizeof(struct reloc_info);
  1297. X   else
  1298. X       nmp->e_hdr->a_trsize = 0;
  1299. X
  1300. X   /* No data relocations */
  1301. X   nmp->e_hdr->a_drsize = 0;
  1302. X   return nmp;
  1303. X}
  1304. END_OF_FILE
  1305. if test 6328 -ne `wc -c <'unstrip.c'`; then
  1306.     echo shar: \"'unstrip.c'\" unpacked with wrong size!
  1307. fi
  1308. # end of 'unstrip.c'
  1309. fi
  1310. if test -f 'util.c' -a "${1}" != "-c" ; then 
  1311.   echo shar: Will not clobber existing file \"'util.c'\"
  1312. else
  1313. echo shar: Extracting \"'util.c'\" \(7655 characters\)
  1314. sed "s/^X//" >'util.c' <<'END_OF_FILE'
  1315. X/*
  1316. X * @(#)util.c  1.2 92/01/22    - a.out & nlist related routines
  1317. X */
  1318. X
  1319. X#include <stdio.h>
  1320. X#include <sys/types.h>
  1321. X#include <string.h>
  1322. X#include <malloc.h>
  1323. X#include <fcntl.h>
  1324. X#include <a.out.h>
  1325. X#ifndef sun
  1326. X#include <nlist.h>
  1327. X#endif
  1328. X#include <sys/stat.h>
  1329. X#ifdef sun
  1330. X#include <sys/mman.h>
  1331. X#include <link.h>
  1332. X#endif
  1333. X#include "defs.h"
  1334. X
  1335. Xvoid
  1336. Xprthdr(hp)
  1337. Xstruct exec *hp;
  1338. X{
  1339. X#ifdef sun
  1340. X   (void)printf(hp->a_dynamic?"DYNAMIC":"STATIC");
  1341. X   (void)printf(" Magic %o Version %u Mach %o\n",
  1342. X           hp->a_magic, hp->a_toolversion,
  1343. X           hp->a_machtype);
  1344. X#else
  1345. X   (void)printf(" Magic %o\n", hp->a_magic);
  1346. X#endif
  1347. X   (void)printf("Text %u Data %u Bss %u Syms %u Entry %#x\n",
  1348. X       hp->a_text, hp->a_data, hp->a_bss, hp->a_syms, hp->a_entry);
  1349. X   (void)printf("Trsize %u Drsize %u\n", hp->a_trsize, hp->a_drsize);
  1350. X   return;
  1351. X}
  1352. X
  1353. Xint
  1354. Xncompare(nlp1, nlp2)
  1355. Xstruct nlist *nlp1, *nlp2;
  1356. X{
  1357. X   return nlp1->n_value - nlp2->n_value;
  1358. X}
  1359. X
  1360. Xint
  1361. Xscompare(nlp1, nlp2)
  1362. Xstruct nlist *nlp1, *nlp2;
  1363. X{
  1364. X   return strcmp(nlp1->n_un.n_name, nlp2->n_un.n_name);
  1365. X}
  1366. X
  1367. Xint
  1368. Xrncompare(nlp1, nlp2)
  1369. Xstruct nlist *nlp1, *nlp2;
  1370. X{
  1371. X   return nlp2->n_value - nlp1->n_value;
  1372. X}
  1373. X
  1374. Xint
  1375. Xrscompare(nlp1, nlp2)
  1376. Xstruct nlist *nlp1, *nlp2;
  1377. X{
  1378. X   return strcmp(nlp2->n_un.n_name, nlp1->n_un.n_name);
  1379. X}
  1380. X
  1381. Xvoid
  1382. Xprtsym(nlp)
  1383. Xstruct nlist *nlp;
  1384. X{
  1385. X   char c;
  1386. X
  1387. X   switch (nlp->n_type & N_TYPE) {
  1388. X   case N_UNDF:
  1389. X       if (nlp->n_value && (nlp->n_type & N_EXT))
  1390. X           c = 'C';
  1391. X       else
  1392. X           c = 'U';
  1393. X       break;
  1394. X   case N_ABS: c = 'A'; break;
  1395. X   case N_TEXT: c = 'T'; break;
  1396. X   case N_DATA: c = 'D'; break;
  1397. X   case N_BSS: c = 'B'; break;
  1398. X   case N_COMM: c = 'C'; break;
  1399. X   case N_FN: c = 'F'; break;
  1400. X   default: c = '?'; break;
  1401. X   }
  1402. X   if (!(nlp->n_type & N_EXT))
  1403. X       c = tolower(c);
  1404. X
  1405. X#ifdef DEBUG
  1406. X   (void)printf("type:%#x other:%#x desc:%#x",
  1407. X       nlp->n_type, nlp->n_other, nlp->n_desc);
  1408. X#endif
  1409. X   (void)printf(tolower(c)=='u'?"\t":N_FORMAT, nlp->n_value);
  1410. X   (void)printf(" %c", c);
  1411. X   (void)printf(" %s", nlp->n_un.n_name);
  1412. X
  1413. X   return;
  1414. X}
  1415. X
  1416. Xstatic char *
  1417. Xreltyp(v)
  1418. Xenum reloc_type v;
  1419. X{
  1420. X#ifdef sun
  1421. X#ifdef sparc
  1422. X   static struct {
  1423. X       enum reloc_type v;
  1424. X       char    *s;
  1425. X   } *x, tab[] = {
  1426. X       RELOC_8,    "R_8",
  1427. X       RELOC_16,   "R_16",
  1428. X       RELOC_32,   "R_32",
  1429. X       RELOC_DISP8,    "DISP8",
  1430. X       RELOC_DISP16,   "DISP16",
  1431. X       RELOC_DISP32,   "DISP32",
  1432. X       RELOC_WDISP30,  "WDISP30",
  1433. X       RELOC_WDISP22,  "WDISP22",
  1434. X       RELOC_HI22, "HI22",
  1435. X       RELOC_22,   "R_22",
  1436. X       RELOC_13,   "R_13",
  1437. X       RELOC_LO10, "LO10",
  1438. X       RELOC_SFA_BASE, "SFA_BASE",
  1439. X       RELOC_SFA_OFF13,    "SFA_OFF13",
  1440. X       RELOC_BASE10,   "BASE10",
  1441. X       RELOC_BASE13,   "BASE13",
  1442. X       RELOC_BASE22,   "BASE22",
  1443. X       RELOC_PC10, "PC10",
  1444. X       RELOC_PC22, "PC22",
  1445. X       RELOC_JMP_TBL,  "JMP_TBL",
  1446. X       RELOC_SEGOFF16, "SEGOFF16",
  1447. X       RELOC_GLOB_DAT, "GLOB_DAT",
  1448. X       RELOC_JMP_SLOT, "JMP_SLOT",
  1449. X       RELOC_RELATIVE, "RELATIVE",
  1450. X       (enum reloc_type)0, NULL,
  1451. X   };
  1452. X
  1453. X   for (x=tab; x->s; x++) {
  1454. X       if (x->v == v)
  1455. X           return x->s;
  1456. X   }
  1457. X#endif /* sparc */
  1458. X#endif /* sun */
  1459. X   return "RELOC_???";
  1460. X}
  1461. X
  1462. X#ifdef sun
  1463. Xvoid
  1464. Xprtrel(rp, nrp, nlp)
  1465. Xstruct reloc_info *rp;
  1466. Xint nrp;
  1467. Xstruct nlist *nlp;
  1468. X{
  1469. X   for (; nrp; nrp--, rp++) {
  1470. X       (void)printf("%08x %s", rp->r_address, reltyp(rp->r_type));
  1471. X       if (rp->r_extern) {
  1472. X#ifdef DEBUG
  1473. X           (void)printf(" -- index %04x --", rp->r_index);
  1474. X#endif
  1475. X           (void)printf(" [");
  1476. X           (void)prtsym(nlp + rp->r_index, 0);
  1477. X           (void)printf("]", rp->r_index);
  1478. X       } else {
  1479. X           (void)printf(" ntype %x", rp->r_index);
  1480. X       }
  1481. X       (void)printf(" + %d (%1$x)\n", rp->r_addend);
  1482. X   }
  1483. X
  1484. X   return;
  1485. X}
  1486. X#endif
  1487. X
  1488. Xstruct execmap *
  1489. Xmapfile(file)
  1490. Xchar *file;
  1491. X{
  1492. X   struct execmap *mp;
  1493. X   struct exec *hp;
  1494. X   int fd;
  1495. X   unsigned long strsize;
  1496. X   struct nlist *nlp;
  1497. X   struct stat stb;
  1498. X   caddr_t addr;
  1499. X
  1500. X   if ((fd = open(file, O_RDONLY)) == -1) {
  1501. X       fprintf(stderr, "%s: ", file); perror("open");
  1502. X       return NULL;
  1503. X   }
  1504. X   if ((mp = (struct execmap *)calloc(1, sizeof(*mp))) == NULL) {
  1505. X       fprintf(stderr, "mapfile: no memory\n");
  1506. X       goto errx;
  1507. X   }
  1508. X#ifdef sun
  1509. X   if (fstat(fd, &stb) < 0) {
  1510. X       perror("stat");
  1511. X       goto errx;
  1512. X   }
  1513. X   if ((addr = mmap((caddr_t)0, stb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0)) == (caddr_t)-1) {
  1514. X       perror("mmap");
  1515. X       goto errx;
  1516. X   }
  1517. X   mp->e_mlen = stb.st_size;
  1518. X   hp = mp->e_hdr = (struct exec *)addr;
  1519. X   if (N_BADMAG(*hp)) {
  1520. X       fprintf(stderr, "%s: bad format\n", file);
  1521. X       goto errx;
  1522. X   }
  1523. X   mp->e_text = addr + N_TXTOFF(*hp);
  1524. X   mp->e_data = addr + N_DATOFF(*hp);
  1525. X   if (hp->a_syms == 0) {
  1526. X       (void)close(fd);
  1527. X       return mp;
  1528. X   }
  1529. X
  1530. X   /* Symbol table */
  1531. X   mp->e_nnlist = hp->a_syms / sizeof(struct nlist);
  1532. X   mp->e_nlist = (struct nlist *)(addr + N_SYMOFF(*hp));
  1533. X   mp->e_sym = (char *)(addr + N_STROFF(*hp));
  1534. X   strsize = *((unsigned long *)mp->e_sym);
  1535. X   if (strsize < 4) {
  1536. X       fprintf(stderr, "Incorrect string table size.\n");
  1537. X       goto errx;
  1538. X   }
  1539. X   if (hp->a_text+hp->a_data+hp->a_syms+
  1540. X       hp->a_trsize+hp->a_drsize + strsize > mp->e_mlen) {
  1541. X       fprintf(stderr, "Giant string table.\n");
  1542. X       goto errx;
  1543. X   }
  1544. X
  1545. X   /* Relocation tables */
  1546. X   if (hp->a_trsize != 0) {
  1547. X       mp->e_ntrel = (hp->a_trsize) / sizeof(struct reloc_info);
  1548. X       mp->e_trel = (struct reloc_info *)(addr + N_TRELOFF(*hp));
  1549. X   }
  1550. X   if (hp->a_drsize != 0) {
  1551. X       mp->e_ndrel = (hp->a_drsize) / sizeof(struct reloc_info);
  1552. X       mp->e_drel = (struct reloc_info *)(addr + N_DRELOFF(*hp));
  1553. X   }
  1554. X
  1555. X#else sun
  1556. X
  1557. X   if ((hp = mp->e_hdr = (struct exec *)malloc(sizeof(struct exec))) == NULL) {
  1558. X       fprintf(stderr, "No memory for header.\n");
  1559. X       goto errx;
  1560. X   }
  1561. X   if (read(fd, (char *)hp, sizeof(struct exec)) < sizeof(struct exec)) {
  1562. X       perror("read");
  1563. X       goto errx;
  1564. X   }
  1565. X   if (N_BADMAG(*hp)) {
  1566. X       fprintf(stderr, "%s: bad format\n", file);
  1567. X       goto errx;
  1568. X   }
  1569. X   if (hp->a_syms == 0) {
  1570. X       (void)close(fd);
  1571. X       return mp;
  1572. X   }
  1573. X   mp->e_nnlist = hp->a_syms / sizeof(struct nlist);
  1574. X   if ((mp->e_nlist = (struct nlist *)malloc(hp->a_syms)) == NULL) {
  1575. X       fprintf(stderr, "No memory for nlist.\n");
  1576. X       goto errx;
  1577. X   }
  1578. X
  1579. X   /* read symbol table */
  1580. X   if (lseek(fd, N_SYMOFF(*hp), 0) < 0) {
  1581. X       perror("seek");
  1582. X       goto errx;
  1583. X   }
  1584. X   if (read(fd, (char *)mp->e_nlist, hp->a_syms) < hp->a_syms) {
  1585. X       perror("read nlist");
  1586. X       goto errx;
  1587. X   }
  1588. X   if (lseek(fd, N_STROFF(*hp), 0) < 0) {
  1589. X       perror("seek");
  1590. X       goto errx;
  1591. X   }
  1592. X   if (read(fd, (char *)&strsize, 4) < 4) {
  1593. X       perror("read strsize");
  1594. X       goto errx;
  1595. X   }
  1596. X   if (strsize < 4) {
  1597. X       fprintf(stderr, "Incorrect string table size.\n");
  1598. X       goto errx;
  1599. X   }
  1600. X   if (lseek(fd, -4, 1) < 0) {
  1601. X       perror("seek");
  1602. X       goto errx;
  1603. X   }
  1604. X   if ((mp->e_sym = malloc(strsize)) == NULL) {
  1605. X       fprintf(stderr, "No memory for strings.\n");
  1606. X       goto errx;
  1607. X   }
  1608. X   if (read(fd, mp->e_sym, strsize) < strsize) {
  1609. X       perror("read strings");
  1610. X       goto errx;
  1611. X   }
  1612. X
  1613. X   /* read relocation tables */
  1614. X   if (hp->a_trsize != 0) {
  1615. X       mp->e_ntrel = (hp->a_trsize) / sizeof(struct reloc_info);
  1616. X       if ((mp->e_trel = (struct reloc_info *)malloc(hp->a_trsize)) == 0) {
  1617. X           fprintf(stderr, "No memory for reloc_info.\n");
  1618. X           goto errx;
  1619. X       }
  1620. X       if (lseek(fd, N_TRELOFF(*hp), 0) < 0) {
  1621. X           perror("seek");
  1622. X           goto errx;
  1623. X       }
  1624. X       if (read(fd, (char *)mp->e_trel, hp->a_trsize) < hp->a_trsize) {
  1625. X           perror("read reloc_info");
  1626. X           goto errx;
  1627. X       }
  1628. X   }
  1629. X   if (hp->a_drsize != 0) {
  1630. X       mp->e_ndrel = (hp->a_drsize) / sizeof(struct reloc_info);
  1631. X       if ((mp->e_drel = (struct reloc_info *)malloc(hp->a_drsize)) == 0) {
  1632. X           fprintf(stderr, "No memory for reloc_info.\n");
  1633. X           goto errx;
  1634. X       }
  1635. X       if (lseek(fd, N_DRELOFF(*hp), 0) < 0) {
  1636. X           perror("seek");
  1637. X           goto errx;
  1638. X       }
  1639. X       if (read(fd, (char *)mp->e_drel, hp->a_drsize) < hp->a_drsize) {
  1640. X           perror("read reloc_info");
  1641. X           goto errx;
  1642. X       }
  1643. X   }
  1644. X#endif sun
  1645. X
  1646. X   (void)close(fd);
  1647. X   /* convert string table offset to char pointer, in situ */
  1648. X   for (nlp = mp->e_nlist; nlp < mp->e_nlist + mp->e_nnlist; nlp++) {
  1649. X       if (nlp->n_un.n_strx > 0 && nlp->n_un.n_strx < strsize)
  1650. X           nlp->n_un.n_name = mp->e_sym + nlp->n_un.n_strx;
  1651. X       else
  1652. X           nlp->n_un.n_name = "sym_???";
  1653. X   }
  1654. X   return mp;
  1655. X
  1656. Xerrx:
  1657. X   (void)close(fd);
  1658. X   return NULL;
  1659. X}
  1660. X
  1661. Xint
  1662. Xunmapfile(mp)
  1663. Xstruct execmap *mp;
  1664. X{
  1665. X#ifdef sun
  1666. X   if (munmap(mp->e_hdr, mp->e_mlen) < 0) {
  1667. X       perror("munmap");
  1668. X       return -1;
  1669. X   }
  1670. X#endif
  1671. X   (void)free((char *)mp);
  1672. X   return 0;
  1673. X}
  1674. X
  1675. END_OF_FILE
  1676. if test 7655 -ne `wc -c <'util.c'`; then
  1677.     echo shar: \"'util.c'\" unpacked with wrong size!
  1678. fi
  1679. # end of 'util.c'
  1680. fi
  1681. echo shar: End of archive 1 \(of 1\).
  1682. cp /dev/null ark1isdone
  1683. MISSING=""
  1684. for I in 1 ; do
  1685.     if test ! -f ark${I}isdone ; then
  1686.     MISSING="${MISSING} ${I}"
  1687.     fi
  1688. done
  1689. if test "${MISSING}" = "" ; then
  1690.     echo You have the archive.
  1691.     rm -f ark[1-9]isdone
  1692. else
  1693.     echo You still need to unpack the following archives:
  1694.     echo "        " ${MISSING}
  1695. fi
  1696. ##  End of shell archive.
  1697. exit 0
  1698.  
  1699.  
  1700. : To unbundle, sh this file
  1701. echo x - mksym.c 1>&2
  1702. sed 's/^X//' >mksym.c <<'@@@End of mksym.c'
  1703. X/* 
  1704. X * Copy just the symbol tables from an application for debugging.
  1705. X * (BSD format: must also copy "string table", the actual name entries).
  1706. X *
  1707. X * $Id: mksym.c,v 1.4 92/02/03 17:28:55 ian Exp $
  1708. X *
  1709. X * Run in makefile just BEFORE stripping.
  1710. X * usage: mksyms a.out # writes on a.out.sym
  1711. X * e.g.,
  1712. X * $(CC) $(AEOBJS) $(AELIBS) $(SYSLIBS) -o ae_2.24
  1713. X * mksyms ae_2.24 # creates ae_2.24.sym
  1714. X * strip ae_2.24
  1715. X *
  1716. X */
  1717. X
  1718. X#include <stdio.h>
  1719. X#include <ctype.h>
  1720. X#include <sys/types.h>
  1721. X#include <sys/stat.h>
  1722. X#include <a.out.h>
  1723. X
  1724. X#define    MAXSTR  1000
  1725. X
  1726. Xint    debug;
  1727. Xstatic struct stat statbuf;
  1728. Xchar   *progname;
  1729. Xvoid   error(), exit();
  1730. Xvoid   closein(), closeout();
  1731. X
  1732. Xstatic char *txbuf, *dtbuf,    /* used to read text and data segments */
  1733. X   *symbuf, *strbuf,   /* symbols */
  1734. X   *txrldbuf,      /* text rld */
  1735. X   *dtrldbuf;      /* data rld */
  1736. Xlong symtabsize, strtabsize;   /* the only ones we need to compute */
  1737. Xlong pigsize;          /* pessimal assumption here... */
  1738. Xchar *malloc();
  1739. X
  1740. Xstatic int ifd, ofd;
  1741. Xstatic struct exec filhdr;
  1742. Xextern int errno;
  1743. X
  1744. X#define max(x,y) (x>y?x:y)
  1745. X
  1746. X/*
  1747. X * main - parse arguments and handle options
  1748. X */
  1749. Xmain(argc, argv)
  1750. Xint argc;
  1751. Xchar *argv[];
  1752. X{
  1753. X   int c, errflg = 0, keepem = 0;
  1754. X   extern int optind;
  1755. X   extern char *optarg;
  1756. X
  1757. X   progname = argv[0];
  1758. X
  1759. X   pigsize = getpagesize();
  1760. X
  1761. X   while ((c = getopt(argc, argv, "d")) != EOF)
  1762. X       switch (c) {
  1763. X       case 'd':
  1764. X           ++debug;
  1765. X           break;
  1766. X       default:
  1767. X           errflg++;
  1768. X           break;
  1769. X       }
  1770. X   if (errflg) {
  1771. X       (void) fprintf(stderr, "usage: %s xxx [file] ...\n", progname);
  1772. X       exit(2);
  1773. X   }
  1774. X
  1775. X   if (argc <= optind) {
  1776. X       fprintf(stderr, "usage: %s a.out > a.syms\n", progname);
  1777. X       exit(3);
  1778. X   }
  1779. X
  1780. X   for (; optind < argc; optind++) {
  1781. X           if (stat(argv[optind], &statbuf) != 0) {
  1782. X               fprintf(stderr,
  1783. X                   "can't fstat %s", argv[optind]);
  1784. X               continue;
  1785. X           }
  1786. X           if ((statbuf.st_mode & S_IFMT)==S_IFDIR) {
  1787. X               fprintf(stderr,
  1788. X                   "%s is a directory!", argv[optind]);
  1789. X               continue;
  1790. X           }
  1791. X           process(argv[optind], debug, statbuf.st_size);
  1792. X       }
  1793. X
  1794. X   exit(0);
  1795. X}
  1796. X
  1797. Xprocess(inname, debug, fsize)
  1798. Xchar *inname;
  1799. Xint debug;
  1800. Xlong fsize;
  1801. X{
  1802. X   char outname[MAXSTR+1];
  1803. X   char *AllTheRest;
  1804. X   long LengthOfTheRest;
  1805. X
  1806. X   strncpy(outname, inname, MAXSTR);
  1807. X   strncat(outname, ".sym", MAXSTR);
  1808. X
  1809. X   /* PART ONE -- read the old format in, and convert */
  1810. X   openin(inname, fsize);  /* sets globals s* based on exec hdr */
  1811. X
  1812. X#define bufalloc(buf,bufsize) if ((buf = malloc((unsigned)bufsize)) == NULL) { \
  1813. X       fprintf(stderr, "%s: can't malloc memory for text/data\n", \
  1814. X           progname); \
  1815. X       exit(4); \
  1816. X       }
  1817. X
  1818. X   LengthOfTheRest = fsize - N_SYMOFF(filhdr);
  1819. X   bufalloc(AllTheRest, LengthOfTheRest);
  1820. X   if (lseek(ifd, N_SYMOFF(filhdr), 0) < 0) {
  1821. X       perror("lseek to start of symbol table on input");
  1822. X       exit(1);
  1823. X   }
  1824. X
  1825. X   {
  1826. X       long i = read(ifd, AllTheRest, LengthOfTheRest);
  1827. X
  1828. X       if (i != LengthOfTheRest) {
  1829. X           extern int errno;
  1830. X           int e = errno;
  1831. X
  1832. X           fprintf(stderr,
  1833. X               "%s: %s: %ld bytes instead of %ld returned by ",
  1834. X               progname, inname, i, LengthOfTheRest);
  1835. X           errno =e;
  1836. X           perror("read()");
  1837. X           exit(1);
  1838. X       }
  1839. X
  1840. X       closein();
  1841. X       openout(outname);
  1842. X
  1843. X       i = write(ofd, AllTheRest, LengthOfTheRest);
  1844. X
  1845. X       if (i != LengthOfTheRest) {
  1846. X           extern int errno;
  1847. X           int e = errno;
  1848. X
  1849. X           fprintf(stderr,
  1850. X               "%s: %s: %ld bytes instead of %ld returned by ",
  1851. X               progname, inname, i, LengthOfTheRest);
  1852. X           errno =e;
  1853. X           perror("write()");
  1854. X           exit(1);
  1855. X       }
  1856. X   }
  1857. X
  1858. X
  1859. X#if 0
  1860. X   bufalloc(symbuf,   symtabsize);
  1861. X   getsyms(symbuf);
  1862. X
  1863. X   bufalloc(strbuf,   strtabsize);
  1864. X   getstrs(strbuf);
  1865. X
  1866. X   closein();
  1867. X
  1868. X   /* PART TWO - write the output file */
  1869. X   openout();
  1870. X   putsyms(symbuf);
  1871. X   putstrs(strbuf);
  1872. X#endif
  1873. X   closeout();
  1874. X
  1875. X   /* CLEAN UP */
  1876. X   if (txbuf) free(txbuf);
  1877. X   if (dtbuf) free(dtbuf);
  1878. X   if (symbuf) free(symbuf);
  1879. X   if (strbuf) free(strbuf);
  1880. X   if (AllTheRest) free(AllTheRest);
  1881. X}
  1882. X
  1883. X
  1884. X/*
  1885. X * Open a a.out for input, read header, return sizes of the
  1886. X * (text, data, sym, trld, drld) segments so a buffer can be allocated.
  1887. X */
  1888. Xopenin(fn, filesize)
  1889. Xchar *fn;
  1890. Xlong filesize;
  1891. X{
  1892. X   int i;
  1893. X
  1894. X   if ((ifd = open(fn, 0)) <0) {
  1895. X       fprintf(stderr, "%s: error opening %s\n", progname, fn);
  1896. X       exit(101);
  1897. X   }
  1898. X
  1899. X   if ((i=read(ifd, (char *)&filhdr, sizeof filhdr)) != sizeof filhdr) {
  1900. X       int realerrno = errno;
  1901. X       fprintf(stderr,
  1902. X           "%s: read exec: errno %d, got %d bytes, wanted %d\n",
  1903. X           progname, realerrno, i, sizeof filhdr);
  1904. X       exit(102);
  1905. X   }
  1906. X
  1907. X   if (N_BADMAG(filhdr)) {
  1908. X       fprintf(stderr,
  1909. X           "%s: bad magic: magic number %ld\n",
  1910. X           progname, filhdr.a_magic);
  1911. X       exit(103);
  1912. X   }
  1913. X
  1914. X   /* Get symtabsize and strtabsize from the input file */
  1915. X
  1916. X   symtabsize = filhdr.a_syms;
  1917. X
  1918. X   lseek(ifd, N_STROFF(filhdr), 0);
  1919. X   if (sizeof strtabsize != read (ifd, &strtabsize, sizeof strtabsize)) {
  1920. X       fprintf(stderr, "can't get size of string table\n");
  1921. X       return;
  1922. X   }
  1923. X
  1924. X   if (debug) {
  1925. X       printf("Name:\t%s\n", fn);
  1926. X       printf("Fsize:\t%d\n", filesize);
  1927. X       printf("Txtsiz:\t%d\n", filhdr.a_magic);
  1928. X       printf("Symsiz:\t%d (from a_syms)\n", symtabsize);
  1929. X       printf("strsiz:\t%d (read from file)\n", strtabsize);
  1930. X       printf("symstart:\t%ld\n", N_SYMOFF(filhdr));
  1931. X   }
  1932. X
  1933. X   return;
  1934. X}
  1935. X
  1936. Xvoid
  1937. Xclosein()
  1938. X{
  1939. X   (void) close(ifd);
  1940. X}
  1941. X
  1942. Xopenout(outn)
  1943. Xchar *outn;
  1944. X{
  1945. X
  1946. X   ofd = creat(outn, 0644);
  1947. X   if (ofd<0) {
  1948. X       perror(outn);
  1949. X       exit(1);
  1950. X   }
  1951. X
  1952. X   if (write(ofd, &filhdr, sizeof filhdr) != sizeof(filhdr)) {
  1953. X       perror("write first header");
  1954. X       exit(1);
  1955. X   }
  1956. X
  1957. X   if (lseek(ofd, (long)N_SYMOFF(filhdr), 0) < 0) {
  1958. X       perror("lseek to start of symbol table on output");
  1959. X       exit(1);
  1960. X   }
  1961. X}
  1962. X
  1963. Xvoid
  1964. Xcloseout()
  1965. X{
  1966. X   (void) close(ofd);
  1967. X}
  1968. X
  1969. Xgettext(buf)
  1970. Xchar *buf;
  1971. X{
  1972. X   if (lseek(ifd, N_TXTOFF(filhdr), 0) <0) {
  1973. X       perror("gettext: lseek");
  1974. X       exit(1);
  1975. X   }
  1976. X   if (read(ifd, (char *)buf, filhdr.a_text) != filhdr.a_text) {
  1977. X       perror("gettext: read");
  1978. X       exit(1);
  1979. X   }
  1980. X   return;
  1981. X}
  1982. X
  1983. Xgetdata(buf)
  1984. Xchar *buf;
  1985. X{
  1986. X   if (lseek(ifd, N_DATOFF(filhdr), 0) <0) {
  1987. X       perror("getdata: lseek");
  1988. X       exit(1);
  1989. X   }
  1990. X   if (read(ifd, (char *)buf, filhdr.a_data) != filhdr.a_data) {
  1991. X       perror("getdata: read");
  1992. X       exit(1);
  1993. X   }
  1994. X   return;
  1995. X}
  1996. X
  1997. Xgetsyms(buf)
  1998. Xchar *buf;
  1999. X{
  2000. X   if (lseek(ifd, N_SYMOFF(filhdr)+sizeof strtabsize, 0) <0) {
  2001. X       perror("getsyms: lseek");
  2002. X       exit(1);
  2003. X   }
  2004. X   if (read(ifd, (char *)buf, symtabsize) != symtabsize) {
  2005. X       perror("getsyms: read");
  2006. X       exit(1);
  2007. X   }
  2008. X}
  2009. X
  2010. Xgetstrs(buf)
  2011. Xchar *buf;
  2012. X{
  2013. X   if (lseek(ifd, N_STROFF(filhdr), 0) <0) {
  2014. X       perror("getstrs: lseek");
  2015. X       exit(1);
  2016. X   }
  2017. X   if (read(ifd, (char *)buf, strtabsize) != strtabsize) {
  2018. X       perror("getstrs: read");
  2019. X       exit(1);
  2020. X   }
  2021. X}
  2022. X
  2023. Xputsyms(buf)
  2024. Xchar *buf;
  2025. X{
  2026. X   if (lseek(ofd, filhdr.a_text+filhdr.a_data, 0) < 0) {
  2027. X       perror("putsyms: seek");
  2028. X       exit(1);
  2029. X   }
  2030. X   if (write(ofd, (char *)buf, symtabsize) != symtabsize) {
  2031. X       perror("putsyms: write");
  2032. X       exit(1);
  2033. X   }
  2034. X}
  2035. X
  2036. Xputstrs(buf)
  2037. Xchar *buf;
  2038. X{
  2039. X   if (write(ofd, (char *)buf, strtabsize) != strtabsize) {
  2040. X       perror("putstrs: write");
  2041. X       exit(1);
  2042. X   }
  2043. X}
  2044. X
  2045. @@@End of mksym.c
  2046.  
  2047.  
  2048. -----BEGIN PGP SIGNATURE-----
  2049. Version: 2.2
  2050.  
  2051. iQCVAgUBLBZikYXSIZRfVL2JAQGgYgP+IL9OhAbjU0ZrsInVimnfOvNrlPArAUyA
  2052. 27HH8YB1jubAhZk8gWASDQubIBSvxHlvgooGvgO2TNQckD5jWOe6a5LZVpfCDgMH
  2053. 63E6/HLzL/uRsdhcLUuNM8GnKNhXeYkaZsfTkzYvnl2So5GwHpxu+BBYf+25xrVs
  2054. KK18HKxKfcE=
  2055. =Z8Kk
  2056. -----END PGP SIGNATURE-----
  2057.